/* vim: set sw=8 ts=8 sts=8 expandtab: */
#ifndef CMAID_ITER_H
#define CMAID_ITER_H

/**
 * @defgroup Cmaid_Iter The Iterator Class
 * @ingroup Classes
 * @brief The class to iterator over the containers
 *
 * The iterator class forms the heart of @em Cmaid and makes @em Cmaid different
 * to other abstract data type libraries. Like in any other data type library
 * you can iterate with them over a container and remove objects from the
 * container, but unlike in other implementations the iterator points still
 * to a valid node if you remove an object, even if you did not removed it
 * with the iterator itself.
 *
 * @section Cmaid_Iter_Attaching Attaching and detaching the iterator
 *
 * Before you can use the iterator you have to attach it to the container,
 * you want to work with. The container will save a reference to the iterator
 * so it can adjust the iterator after a node was removed or added. Keep in
 * mind to @b always detach an iterator after the iterator is not be used
 * any longer, for example if it is going to be out of scope.
 *
 * Example:
 * @code
 * extern Cmaid_Container *c;
 * Cmaid_Iter it;
 *
 * cmaid_container_iter_attach(c, &it);
 * // work with the iterator
 * cmaid_container_iter_detach(c, &it);
 * @endcode
 *
 * @section Cmaid_Iter_Concept The circular concept of the iterators
 *
 * The underlying concept of iterators is a circular list. You can figure this
 * with having a empty node that links the beginning with the end. After the
 * iterator was attached to a container or after calling cmaid_iter_start(),
 * the iterator is pointing to this empty node. Calling cmaid_iter_current()
 * will return NULL, because the node is empty, but calling cmaid_iter_next()
 * will perform a step to the next node, i.e. the first node and returns it
 * value. The same works for cmaid_iter_previous().
 *
 * @dot
 *      digraph iters {
 *              rankdir=LR;
 *              start -> nullnode [label="attach()",
 *                      labelURL="\ref cmaid_container_iter_attach()"];
 *              nullnode -> node0 -> node1 -> node2 ->
 *              dotnode -> nodeN -> nullnode [label="next()",
 *                      labelURL="\ref cmaid_iter_next()"];
 *              start [label="",style=filled,color=black,shape=doublecircle];
 *              nullnode [label="NULL-Node\nIndex \< 0",color=blue];
 *              node0 [label="Node 0"];
 *              node1 [label="Node 1"];
 *              node2 [label="Node 2"];
 *              nodeN [label="Node N"];
 *              dotnode [label="...",shape=none];
 *              {rank=same; node0; nodeN;}
 *              {rank=same; node1; dotnode;}
 *      }
 * @enddot
 *
 * Example:
 * @code
 * cmaid_iter_start(&it); // "it" is pointing to the node before the first node
 * cmaid_iter_next(&it);  // "it" points now to the first node, if the container
 *                        // is not empty
 * while ((item = cmaid_iter_next(&it))
 *      printf("%s\n", item); // prints every string in the container except
 *                            // the first one
 * // "it" is now pointing to the node before the first node again
 * @endcode
 */
/**
 * @brief Type definition of the Iterator Class
 * @ingroup Cmaid_Iter
 */
typedef struct Cmaid_Iter Cmaid_Iter;

/**
 * @brief Type definition of the Container Class
 * @ingroup Cmaid_Container
 */
typedef struct Cmaid_Container Cmaid_Container;

/**
 * @defgroup Cmaid_Iter_Interface The Iterator Interface
 * @ingroup Cmaid_Iter
 *
 * You only have to deal with the interface structure directly, if you are
 * going to write an implementation of the interface. Else you can safely
 * ignore this.
 *
 * @{
 */
/** Type definition for the @em start callback */
typedef void  (*Cmaid_Iter_Start_Cb) (Cmaid_Iter *it);
/** Type definition for the @em goto @em iter callback */
typedef void *(*Cmaid_Iter_Iter_Goto_Cb) (Cmaid_Iter *it, const Cmaid_Iter *to_it);
/** Type definition for the @em goto @em index callback */
typedef void *(*Cmaid_Iter_Index_Goto_Cb) (Cmaid_Iter *it, int index);
/** Type definition for the @em goto callback */
typedef void *(*Cmaid_Iter_Goto_Cb) (Cmaid_Iter *it, const void *data);
/** Type definition for the @em current callback */
typedef void *(*Cmaid_Iter_Current_Cb) (Cmaid_Iter *it);
/** Type definition for the @em next callback */
typedef void *(*Cmaid_Iter_Next_Cb) (Cmaid_Iter *it);
/** Type definition for the @em previous callback */
typedef void *(*Cmaid_Iter_Previous_Cb) (Cmaid_Iter *it);
/** Type definition for the @em remove callback */
typedef void  (*Cmaid_Iter_Remove_Cb) (Cmaid_Iter *it);

/** Type definition for the @em iter interface */
typedef struct Cmaid_Iter_Interface Cmaid_Iter_Interface;

/**
 * @brief The Iter Interface structure
 * The iterator interface provides functions to navigate through a container.
 */
struct Cmaid_Iter_Interface
{
        Cmaid_Iter_Start_Cb       start;
        Cmaid_Iter_Iter_Goto_Cb   iter_goto;
        Cmaid_Iter_Index_Goto_Cb  index_goto;
        Cmaid_Iter_Goto_Cb        data_goto;
        Cmaid_Iter_Current_Cb     current;
        Cmaid_Iter_Next_Cb        next;
        Cmaid_Iter_Previous_Cb    previous;
        Cmaid_Iter_Remove_Cb      remove;
};
/**
 * @}
 */

/**
 * @addtogroup Cmaid_Iter
 * @{
 */
/**
 * @brief The Iterator Class structure
 * Do not manipulate the attributes directly.
 */
struct Cmaid_Iter
{
        const Cmaid_Iter_Interface *interface;
        Cmaid_Iter    *next;
        void          *container;
        void          *current;
        int            index;
        int            bucket;
};

CMAID_INLINE Cmaid_Iter *cmaid_iter_new(void);
CMAID_INLINE void        cmaid_iter_destroy(Cmaid_Iter *it);

CMAID_INLINE void        cmaid_iter_start(Cmaid_Iter *it);
CMAID_INLINE void       *cmaid_iter_iter_goto(Cmaid_Iter *it,
                                                const Cmaid_Iter *to_it);
CMAID_INLINE void       *cmaid_iter_index_goto(Cmaid_Iter *it, 
                                                int index);
CMAID_INLINE void       *cmaid_iter_goto(Cmaid_Iter *it, const void *data);
CMAID_INLINE int         cmaid_iter_index_get(Cmaid_Iter *it);
CMAID_INLINE void       *cmaid_iter_container_get(Cmaid_Iter *it);
CMAID_INLINE void       *cmaid_iter_current(Cmaid_Iter *it);
CMAID_INLINE void       *cmaid_iter_next(Cmaid_Iter *it);
CMAID_INLINE void       *cmaid_iter_previous(Cmaid_Iter *it);
CMAID_INLINE void        cmaid_iter_remove(Cmaid_Iter *it);

void                     cmaid_iter_empty_attach(Cmaid_Iter *it);
unsigned int             cmaid_iter_empty_detach(Cmaid_Iter *it);

extern const Cmaid_Iter_Interface cmaid_iter_null_if;
/**
 * @}
 */
#include <cmaid_iter_funcdef.h>

#endif /* CMAID_ITER_H */
